// ManipulatorWindow.h

#ifndef MANIPULATORWINDOW_H__
#define MANIPULATORWINDOW_H__

#define GL3_PROTOTYPES

// Include the vector and matrix utilities from the textbook, as well as some
// macro definitions.
#include "Angel.h"

#include "AbstractGLUTWindow.h"
#include "SimpleGLUTApplication.h"
#include "DebugHelper.h"
#include "GLScene.h"


#define GL3_PROTOTYPES

// Include the vector and matrix utilities from the textbook, as well as some
// macro definitions.
#include "Angel.h"

#ifdef __APPLE__
#  include <OpenGL/gl3.h>
#endif

#include <typeinfo>

#include "Angel.h"
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fstream>
#include <iostream>
#include <string>
#include <stdlib.h>
#include <dirent.h>
#include <boost/algorithm/string.hpp>
#include <vector>

#include "DebugHelper.h"
#include "ConcreteGLObject3D.h"
#include "GLScene.h"
#include "SimpleGLUTApplication.h"
#include "ManipulatorGLObject.h"

using namespace std;
using namespace boost;
using namespace Voltron;



namespace Voltron
{
//	class SimpleGLUTApplication;
	
	class ManipulatorWindow: public AbstractGLUTWindow
	{
	
		private:
		
		// Private Constructors
		// Private Destructor
		// Private properties
		// Private members
		
		protected:

		// Protected Constructors
		// Protected Destructor
		// Protected properties
		// Protected members

		public:
		
	
		// Public Constructors
		ManipulatorWindow();
		ManipulatorWindow(string title,  int windowXpos, int windowYpos, int windowHeight, int windowWidth);
		
		// Public Destructor
		~ManipulatorWindow();

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		
		// Public properties
		string scenePath;
		typedef Angel::vec4  color4;
		typedef Angel::vec4  point4;
		GLuint  model_view;  // model-view matrix uniform shader variable location
		GLuint  projection; // projection matrix uniform shader variable location
		mat4 model, view, mv,transformed, ident; //model matrix, view matrix, combined model-view matrix
		
		//Variables for the menus
		int objectSubMenu;
		int sceneSubMenu;
		int sceneRotationSubMenu;
		int loadObjectsMenu;
		vector <string> objectNames;
		
		//Variables for selection
		int objectID;
		int picked;
		GLint flag;
		
		//Variables for mouse movement
		int lastX, lastY;
		int mouseDown;
		
		//Variables for transforms
		int transformMode;
		int modelMode;
		// ^^ need these here for the moment to compile without a bunch of changes
				
		// globals
		GLuint shaderprogram;
		GLScene *_scene;
		GLObject3D* globj;
		
		ManipulatorGLObject *_manipulatorobj;

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		
		// Public members
		void init();
		void initWindow();
		void initWindow(string title,  int windowXpos, int windowYpos, int windowHeight, int windowWidth, char *argv[]);
		void initView(char *argv[]);
		void initCallbacks();
		mat4 translate(int mode, int dx, int dy);
		mat4 rotate(int mode, int dx, int dy);
		mat4 scale(int mode, int dx, int dy);
		void objectMenu(int value);
		void sceneMenu(int value);
		void sceneRotationMenu(int value);
		void mainMenu(int value);
		vector <string> getFileNames(const string directory);
		void populateObjectMenu(vector<string> objNames);
		void loadObjectMenu(int value);
		void createMenu(void);

		// event handlers go here
		void onReshape(int windowWidth, int windowHeight);
		void onDisplay(void);
		void onKeyboard(unsigned char key, int x, int y);
		void onSpecial(int key, int x, int y);
		void onMouse(int button, int state, int x, int y);
		void onMotion(int x, int y);   

		// GLUT Callbacks had to be added to wrap the event handlers in a singleton instance
		static void onReshapeCallback(int windowWidth, int windowHeight);
		static void onDisplayCallback(void);
		static void onKeyboardCallback(unsigned char key, int x, int y);
		static void onSpecialCallback(int key, int x, int y);
		static void onMouseCallback(int button, int state, int x, int y);
		static void onMotionCallback(int x, int y);   

		static void loadObjectMenuCallback(int value);
		static void objectMenuCallback(int value);
		static void sceneMenuCallback(int value);
		static void sceneRotationMenuCallback(int value);
		static void mainMenuCallback(int value);
		
	};
	
// A singleton window was added to aid in wrapping the event handlers
// This is now a single window that can be accessed anywhere.
typedef Singleton<ManipulatorWindow> ManipulatorWindowSingleton;

	
}
#endif







